<template>
  <div class="w-[80vh] h-[80vh] relative">
    <div class="bg-blue-500 w-12 h-12 rounded-3xl fixed left-[49%] top-50" id='ball'></div>
  </div>
</template>

<script lang="ts" setup name="RXjs-拖动小球">
import { fromEvent } from 'rxjs';
import { map, switchMap, takeUntil } from 'rxjs/operators';
// @ts-ignore
onMounted(() => {
  let ball: HTMLElement = document.getElementById('ball')!;
  const getMouseEventPos = (event: MouseEvent) => {
    return {
      x: event.clientX,
      y: event.clientY
    };
  }
  const mousedown$ = fromEvent<MouseEvent>(ball, 'mousedown').pipe(
    map(getMouseEventPos)
  );
  const mousemove$ = fromEvent<MouseEvent>(document, 'mousemove').pipe(
    map(getMouseEventPos)
  );
  const mouseup$ = fromEvent<MouseEvent>(document, 'mouseup');
  const drag$ = mousedown$.pipe(
    switchMap(initialPos => {
      const { top, left } = ball.getBoundingClientRect();
      return mousemove$.pipe(
        map(({ x, y }) => ({
          top: y - initialPos.y + top,
          left: x - initialPos.x + left
        })),
        takeUntil(mouseup$)
      );
    })
  );
  drag$.subscribe(({ top, left }) => {
    ball.style.top = `${top}px`;
    ball.style.left = `${left}px`;
    ball.style.bottom = '';
    ball.style.right = '';
  });
})

</script>